#include "ftpservice.hpp"
#include <cctype>
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <vector>
using std::vector;
using namespace boost::posix_time;
using namespace com_oocl_monitor::service;
using namespace com_oocl_monitor::domain;
using namespace com_oocl_monitor::system;

FtpService::FtpService(FtpPool *pool)
	: _pool(pool) {
}

FtpService::~FtpService() {
}

DataCollection *FtpService::perform(const Profile profile, const ptime startTime, const ptime endTime) {
	string url = _pool->Host();
	if (url.substr(0, 6) != "ftp://")
		throw FtpException(_pool->Host());
	DataCollection *data = nullptr;
	Connection *con = _pool->getConnection();
	//    curl_easy_setopt(con, CURLOPT_VERBOSE, 1L);
	curl_easy_setopt(con, CURLOPT_TIMEOUT, 120);
	if (profile._uri != "")
		url += profile._uri;
	if (_pool->Port() != "") {
		long port;
		stringstream ss;
		ss << _pool->Port();
		ss>>port;
		curl_easy_setopt(con, CURLOPT_PORT, port);
	}
	curl_easy_setopt(con, CURLOPT_URL, url.c_str());
	if (_pool->Usr() != "" && _pool->Pwd() != "")
		curl_easy_setopt(con, CURLOPT_USERPWD, (_pool->Usr() + ":" + _pool->Pwd()).c_str());
	curl_easy_setopt(con, CURLOPT_WRITEFUNCTION, write_fun);
	curl_easy_setopt(con, CURLOPT_WRITEDATA, &_cache);
	curl_easy_setopt(con, CURLOPT_NOSIGNAL, 1L);
	curl_easy_setopt(con,CURLOPT_FORBID_REUSE,1L);
	curl_easy_setopt(con,CURLOPT_FTPPORT,"-");
	CURLcode code = curl_easy_perform(con);
	if (code != CURLE_OK) {
		_pool->releaseConnection(con);
		throw FtpException(_pool->Host());
	}
	_pool->releaseConnection(con);

	data = cacheToData(profile, startTime, endTime);
	return data;
}

size_t FtpService::write_fun(char * buff, size_t size, size_t nmenb, void * data) {
	stringstream *ss = static_cast<stringstream*> (data);
	ss->write(buff, size * nmenb);
	return size*nmenb;
}

DataCollection *FtpService::cacheToData(const Profile& profile, const ptime& startTime, const ptime& endTime) {
	DataCollection *result = new DataCollection(profile._regexPattern);
	stringstream unixSs;
	time_input_facet *unixF = new time_input_facet("%b %d %Y %H:%M");
	unixSs.imbue(std::locale(unixSs.getloc(), unixF));
	stringstream dosSs;
	time_input_facet *dosF = new time_input_facet("%m-%d-%y %H:%M");
	dosSs.imbue(std::locale(dosSs.getloc(), dosF));
	string line;
	while (getline(_cache, line)) {
		DataPair data;
		if (isdigit(line[0]) && line.find("<DIR>") == string::npos){
			data = parseDOSLine(line,dosSs);
		}
		else if (line[0] == '-')
		{
			data = parseUNIXLine(line,unixSs);
		}
		else
			continue;
		if (profile._dataDirection == "INBOUND") {
			if (data.second._dateTime >= startTime && data.second._dateTime <= endTime)
				result->insert(data);
		} else if (profile._dataDirection == "OUTBOUND") {
			result->insert(data);
		}
	}
	return result;
}

inline DataPair FtpService::parseUNIXLine(const string &line,stringstream &ss) {
	ss.str("");
	ss.clear();
	DataPair dp;
	string date, time, fileName, tmp;
	size_t size;
	ss.write(line.c_str(), line.length());
	for (int i = 0; i < 4; i++)
		ss >> tmp;
	ss>>size;
	ss>>date;
	ss>>tmp;
	if (tmp.length() == 1)
		tmp.insert(0, "0");
	date += " " + tmp;
	ss>>time;
	if (time.find(":") != string::npos) {
		ptime today = second_clock::local_time();
		tmp = to_iso_string(today).substr(0, 4);
		date += " " + tmp;
		date += " " + time;
	} else {
		tmp = "00:00";
		date += time + " " + tmp;
	}
	getline(ss, fileName);
	boost::trim(fileName);
	ss.clear();
	ss.str("");
	ss.write(date.c_str(), date.size());
	ss >> dp.second._dateTime;
	dp.first = fileName;
	dp.second._size = size;
	return dp;
}
//-rw-rw-rw-   1 user     group       36517 Sep  7 09:30 SHIPPING_WMS_20150828170030954_3002904575.xml

inline DataPair FtpService::parseDOSLine(const string &line,stringstream &ss) {
	ss.str("");
	ss.clear();
	DataPair dp;
	string date, time, fileName;
	size_t size;
	ss.write(line.c_str(), line.length());
	ss>>date;
	ss>>time;
	ss>>size;
	getline(ss, fileName);
	boost::trim(fileName);
	if ((time.find("AM") != string::npos) && time.substr(0, 2) == "12") {
		ss.str("");
		ss.clear();
		ss << "00";
		ss << time.substr(2, 3);
		ss >> time;
	}
	else if ((time.find("PM") != string::npos) && (time.substr(0,2) != "12")) {
		ss.str("");
		ss.clear();
		ss << time.substr(0, 2);
		int h;
		ss>>h;
		h += 12;
		ss.str("");
		ss.clear();
		ss << h;
		ss << time.substr(2, 3);
		ss>>time;
	} else
		time = time.substr(0, 5);
	dp.first = fileName;
	string dateTime = date + " " + time;
	ss.clear();
	ss.str("");
	ss.write(dateTime.c_str(), dateTime.size());
	ss >> dp.second._dateTime;
	dp.second._size = size;
	return dp;
}
//09-12-15  11:30PM                    2 haha - Copy (2).txt
//09-13-15  01:05AM                    0 aaa.txt
